package com.mcc.app.siloReport.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mcc.app.cache.domain.PlcCache;
import com.mcc.app.cache.service.IPlcCacheService;
import com.mcc.app.siloReport.domain.SiloDayReport;
import com.mcc.app.siloReport.mapper.SiloDayReportMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

@Component
@EnableScheduling
public class siloReportTask {
    @Autowired
    private IPlcCacheService plcCacheService;

    @Autowired
    private SiloDayReportMapper siloDayReportMapper;

    private static final Set<String> EXCLUDED_FIELDS_8 = new HashSet<>(Arrays.asList(
            "id", "dt", "st2AllNight", "st2AllWhite", "st2AllMid", "st2AllDaily"));
    private static final Set<String> EXCLUDED_FIELDS_0 = new HashSet<>(Arrays.asList(
            "id", "dt", "st2AllNight", "st2AllWhite", "st2AllMid", "st2AllDaily",
            "st2Night1Total", "st2Night2Total", "st2Night3Total", "st2Night4Total",
            "st2Night5Total", "st2Night6Total", "st2Night7Total", "st2Night8Total",
            "st2Night9Total", "st2Night10Total", "st2Night11Total", "st2Night12Total",
            "st2Night13Total", "st2Night14Total", "st2Night15Total", "st2Night16Total",
            "st2Night17Total", "st2Night18Total", "st2Night19Total", "st2Night20Total",
            "st2Night21Total", "st2Night22Total", "st2Night23Total", "st2AllNight"));

    @Scheduled(cron = "0 10 8 * * *")
    public void getSiloReport() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Calendar calendar = Calendar.getInstance();
        // 往前推一小时
        calendar.add(Calendar.HOUR_OF_DAY, -1);
        // 设置时间为当天的 00:00:00
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dt", calendar.getTime());
        if (siloDayReportMapper.selectList(queryWrapper).size() > 0) {
            return;
        }

        List<PlcCache> plcCacheList = plcCacheService.selectPlcCacheByTag("配料");
        // 将 PLC 缓存列表转换为 Map<code, value>
        Map<String, String> cacheMap = new HashMap<>();
        for (PlcCache cache : plcCacheList) {
            String camelKey = toCamelCase(cache.getCacheCode());
            cacheMap.put(camelKey, cache.getCacheValue());
        }
//        System.out.println(cacheMap);
        // 获取 Silo 类的所有字段（包含父类）
        List<Field> fields = getAllFields(SiloDayReport.class,EXCLUDED_FIELDS_8);
        SiloDayReport siloDayReport = SiloDayReport.class.getDeclaredConstructor().newInstance();
        // 遍历字段进行映射
        for (Field field : fields) {
            String fieldName = field.getName();
            String cacheValue = cacheMap.get(fieldName);

            if (cacheValue != null && !cacheValue.isEmpty()) {
                try {
                    Method setter = getSetterMethod(SiloDayReport.class, field);
                    Object convertedValue = convertToTargetType(cacheValue, field.getType());
                    setter.invoke(siloDayReport, convertedValue);
                } catch (NoSuchMethodException e) {
                    System.err.println("[Warn] Setter missing for field: " + fieldName);
                } catch (NumberFormatException e) {
                    System.err.println("[Error] Invalid number format for field " + fieldName
                            + ", value: " + cacheValue);
                }
            }
        }
        siloDayReport.setDt(calendar.getTime());

        siloDayReportMapper.insert(siloDayReport);

    }

    @Scheduled(cron = "0 10 0 * * *")
    public void getSiloReport1() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Calendar calendar = Calendar.getInstance();
        // 往前推一小时
        calendar.add(Calendar.HOUR_OF_DAY, -1);
        // 设置时间为当天的 00:00:00
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dt", calendar.getTime());
        SiloDayReport originSiloDayReport = siloDayReportMapper.selectOne(queryWrapper);
        Long updateId = originSiloDayReport.getId();

        List<PlcCache> plcCacheList = plcCacheService.selectPlcCacheByTag("配料");
        // 将 PLC 缓存列表转换为 Map<code, value>
        Map<String, String> cacheMap = new HashMap<>();
        for (PlcCache cache : plcCacheList) {
            String camelKey = toCamelCase(cache.getCacheCode());
            cacheMap.put(camelKey, cache.getCacheValue());
        }
//        System.out.println(cacheMap);
        // 获取 Silo 类的所有字段（包含父类）
        List<Field> fields = getAllFields(SiloDayReport.class,EXCLUDED_FIELDS_0);
        SiloDayReport siloDayReport = SiloDayReport.class.getDeclaredConstructor().newInstance();
        // 遍历字段进行映射
        for (Field field : fields) {
            String fieldName = field.getName();
            String cacheValue = cacheMap.get(fieldName);

            if (cacheValue != null && !cacheValue.isEmpty()) {
                try {
                    Method setter = getSetterMethod(SiloDayReport.class, field);
                    Object convertedValue = convertToTargetType(cacheValue, field.getType());
                    setter.invoke(siloDayReport, convertedValue);
                } catch (NoSuchMethodException e) {
                    System.err.println("[Warn] Setter missing for field: " + fieldName);
                } catch (NumberFormatException e) {
                    System.err.println("[Error] Invalid number format for field " + fieldName
                            + ", value: " + cacheValue);
                }
            }
        }
        siloDayReport.setId(updateId);

        siloDayReportMapper.updateById(siloDayReport);

    }

    /**
     * 转驼峰命名
     */
    private String toCamelCase(String input) {
        if (input == null || input.isEmpty()) return input;

        StringBuilder sb = new StringBuilder();
        String[] parts = input.split("_");

        sb.append(parts[0]); // 保留第一个部分原样

        for (int i = 1; i < parts.length; i++) {
            if (!parts[i].isEmpty()) {
                // 首字母大写 + 后续小写
                sb.append(Character.toUpperCase(parts[i].charAt(0)));
                if (parts[i].length() > 1) {
                    sb.append(parts[i].substring(1).toLowerCase());
                }
            }
        }
        return sb.toString();
    }

    /**
     * 获取类及其父类的所有字段
     */
    private List<Field> getAllFields(Class<?> clazz, Set<String> excludedFields) {
        List<Field> fields = new ArrayList<>();
        Class<?> currentClass = clazz;
        while (currentClass != null) {
            for (Field field : currentClass.getDeclaredFields()) {
                if (!excludedFields.contains(field.getName())) {
                    fields.add(field);
                }
            }
            currentClass = currentClass.getSuperclass();
        }
        return fields;
    }

    /**
     * 根据字段获取对应的 setter 方法
     */
    private Method getSetterMethod(Class<?> clazz, Field field)
            throws NoSuchMethodException {
        String setterName = "set" + capitalize(field.getName());
        return clazz.getMethod(setterName, field.getType());
    }

    /**
     * 类型转换核心方法（支持 String/Double/Integer/Long 等类型）
     */
    private Object convertToTargetType(String value, Class<?> targetType) {
        try {
            if (targetType == String.class) {
                return value;
            } else if (targetType == Double.class || targetType == double.class) {
                return Double.parseDouble(value);
            } else if (targetType == Integer.class || targetType == int.class) {
                return Integer.parseInt(value);
            } else if (targetType == Long.class || targetType == long.class) {
                return Long.parseLong(value);
            } else if (targetType == Float.class || targetType == float.class) {
                return Float.parseFloat(value);
            } else {
                throw new IllegalArgumentException("Unsupported type: " + targetType);
            }
        } catch (NumberFormatException e) {
            throw new NumberFormatException("Cannot convert '" + value
                    + "' to type " + targetType.getSimpleName());
        }
    }

    /**
     * 字符串首字母大写
     */
    private String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
}
